/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package me.tomato3017.plugins.epicmusic.config;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import me.tomato3017.plugins.epicmusic.EpicMusic;
import me.tomato3017.plugins.epicmusic.audio.AmbientMusicData;
import me.tomato3017.plugins.epicmusic.audio.MusicData;
import me.tomato3017.plugins.epicmusic.region.RegionManager;
import me.tomato3017.plugins.epicmusic.region.WorldData;
import org.bukkit.util.config.Configuration;

/**
 *
 * @author Anthony Kirksey <Anthony.Kirksey@gmail.com>
 */
public class ConfigManager {
    EpicMusic plugin;
    public int CURRENT_FILE_VERSION = 2;
    public int DEFAULT_SONG_LENGTH = 600000; //10 minutes
    
    private Configuration config;

    //config data
    private boolean DEBUG = false;
    private int debugLevel;
    private int fileVersion;
    private int defaultSongLength;
    private int defaultSoundEffectDistance;
    private boolean precacheData;
    HashMap<String,MusicData> musicAliases; //Holds all music URL aliases
    private HashMap<String,AmbientMusicData> ambientAliases; //Holds all ambient music URL aliases
    private int timeBetween;
    
    public ConfigManager(EpicMusic plugin) {
        this.plugin = plugin;
        
        config = plugin.getConfiguration();
    }
    
    /*
     * Loads the configuration from EpicMusic/config.yml
     */
    public void loadConfig(){
        List<String> aliasList;
        List<String> worldList;
        
        //Set of all URL data to tell spout to preload
        HashSet<String> preloadURL = new HashSet<String>();
        
        //First lets load the config from file.
        config.load();
       
        DEBUG = config.getBoolean("debug", false); //DEBUG flag
        debugLevel = config.getInt("debuglevel", 1);
        
        fileVersion = config.getInt("fileversion", CURRENT_FILE_VERSION); //fileversion
        if(fileVersion < CURRENT_FILE_VERSION)
            EpicMusic.log("File version older then current, attempting to load!");
        
        defaultSongLength = config.getInt("defaultlength", DEFAULT_SONG_LENGTH); //song length if not defined in the config
        defaultSoundEffectDistance = (int) Math.pow(config.getInt("defaultsoundeffectdistance", 40), 2);
        precacheData = config.getBoolean("precache", false);
        timeBetween = config.getInt("timebetween", 10000);
        
        //Load the Aliases
        aliasList = config.getKeys("songaliases");
        if(aliasList == null){
            aliasList = new ArrayList<String>();
        }
        //Increment through each song alias
        //TODO: Put these aliases into 1 superclassed hashmap.
        musicAliases = new HashMap<String, MusicData>();
        ambientAliases = new HashMap<String, AmbientMusicData>();
        EpicMusic.log("====LOADING ALIASES====");
        for(String alias : aliasList){
            String aliasPath = "songaliases." + alias;
            
            boolean isAmbient = config.getBoolean(aliasPath + ".ambient", false);
            int songLength = config.getInt(aliasPath + ".length", defaultSongLength);
            int volume = config.getInt(aliasPath + ".volume", 100);
            String URL = config.getString(aliasPath + ".url");

            if(URL != null){
                if(!isAmbient){
                    MusicData songData = new MusicData(URL, alias, songLength, volume);
                    musicAliases.put(alias, songData);
                }
                else{
                    AmbientMusicData songData = new AmbientMusicData(true, URL, alias, songLength, volume);
                    ambientAliases.put(alias, songData);
                }
            }
            else{
                EpicMusic.log("-ERROR- Invalid music URL at alias: " + alias);
            }
            
            
        }
        EpicMusic.log("Aliases loaded! Total: " + musicAliases.size());
        EpicMusic.log("Ambient Aliases loaded! Total: " + ambientAliases.size());
        EpicMusic.log("=====LOADING WORLDS=====");
        
        //Load the world Data     
        worldList = config.getKeys("worlds");
        if(worldList == null){
            worldList = new ArrayList<String>();
        }
        
        
        RegionManager rmanager = EpicMusic.getRegionManager();
        
        for(String world : worldList){
            String worldPath = "worlds." + world;
            WorldData worldData = new WorldData();
            
            //Grab the music
            List<String> musicPlaylist = config.getStringList(worldPath + ".music", null);
            
            for(String music : musicPlaylist){
                worldData.addMusic(resolveAlias(music));
                
            }
            
            //grab each worlds ambient noise
            String ambientMusic = config.getString(worldPath + ".ambient", null);
            int ambientMusicDist = (int) Math.pow(config.getInt(worldPath + ".ambientmusicdist", defaultSoundEffectDistance),2);
            if(ambientMusic != null){
                worldData.setAmbientMusic(resolveAmbientAlias(ambientMusic));
                worldData.setSoundEffectDistance(ambientMusicDist);
            }
            
            //Set the region name
            worldData.setRegionName(world);
            //Store the newly created region into the region cache.
            rmanager.AddRegion(worldData);
            EpicMusic.log("Loaded world:" + worldData.getRegionName() + " Songs:" + worldData.getMusicPlaylist().size());
        }
        
        //get the underground alias
        String undergroundAlias = config.getString("undergroundambient");
        EpicMusic.getRegionManager().setUndergroundMusic(resolveAmbientAlias(undergroundAlias), null);
        
        //flush any changes to disk
        config.save();
        
    }
    
    /*
     * Saves the configuration to EpicMusic/cpnfig.yml
     */
    public void saveConfig(){
        config.save();
    }

    /**
     * @return the DEBUG
     */
    public boolean isDEBUG() {
        return DEBUG;
    }

    /**
     * @param DEBUG the DEBUG to set
     */
    public void setDEBUG(boolean DEBUG) {
        this.DEBUG = DEBUG;
    }
   
    /*
     * Returns the Music object for the requested alias. Null if it doesn't exist.
     */    
    public MusicData resolveAlias(String alias){
        if(alias != null){
            return musicAliases.get(alias);
        }
        
        return null;
    }
    
    /*
     * Returns the Music object for the requested alias. Null if it doesn't exist.
     */
    public AmbientMusicData resolveAmbientAlias(String alias){
        if(alias != null){
            return ambientAliases.get(alias);
        }
        
        return null;
    }
    
    public int getDefaultSongLength(){
        return DEFAULT_SONG_LENGTH;
    }

    public int getDebugLevel() {
        return debugLevel;
    }

    public void setDebugLevel(int debugLevel) {
        this.debugLevel = debugLevel;
    }

    public int getMinSoundEffectDistance() {
        return defaultSoundEffectDistance;
    }

    public int getTimeBetween() {
        return timeBetween;
    }
    
    //Returns a list of strings of aliases
    public List<String> getAliasList(){
        ArrayList<String> list = new ArrayList<String>(musicAliases.keySet());
       
        Collections.sort(list);
        return list;
    }
    
}
